# -*- codeing = utf-8 -*-
# @File :jobApi.py
import operator

from py2neo import Graph
from flask import Blueprint, request
from sqlalchemy import func, distinct
from sqlalchemy.sql import label
from flask import jsonify
import json
from openai import OpenAI

from algorithm import ItemCF, UserCF
from base.code import ResponseCode, ResponseMessage
from base.core import db
from base.response import ResMsg
from hdfs_util import read_hdfs_file
from models.model import chart_data
from models.job import getWords, Job, job_schema, TbExamPaper
from utils.mytool import formatDegree
from models.job import TbItem,TbRate,TbUserFeature
# 从 UserCF.py 中导入 GRNN_DE_Recommender 类
from algorithm.UserCF import GRNN_DE_Recommender
from models.model import User


jobBp = Blueprint("job", __name__)
# 阅读题的难度分析
@jobBp.route('/ReadPrediction_results1Hdfs', methods=['GET'])
def ReadPrediction_results1Hdfs():
    hdfs_file_path = '/AfterCleanData/prediction_results1.json'
    file_content = read_hdfs_file(hdfs_file_path)
    if file_content.startswith("读取失败"):
        return jsonify({'code': 500, 'msg': file_content})

    try:
        data = json.loads(file_content)
        return jsonify({'code': 200, 'msg': '读取成功', 'data': data})
    except Exception as e:
        return jsonify({'code': 500, 'msg': f'解析JSON失败: {e}'})

@jobBp.route('/ReadPrediction_results2Hdfs', methods=['GET'])
def ReadPrediction_results2Hdfs():
    hdfs_file_path = '/AfterCleanData/prediction_results2.json'
    file_content = read_hdfs_file(hdfs_file_path)
    if file_content.startswith("读取失败"):
        return jsonify({'code': 500, 'msg': file_content})

    try:
        data = json.loads(file_content)
        return jsonify({'code': 200, 'msg': '读取成功', 'data': data})
    except Exception as e:
        return jsonify({'code': 500, 'msg': f'解析JSON失败: {e}'})



# 按题型分类获取热门推荐(ItemCF)
@jobBp.route('/hot_by_type', methods=['GET'])
def hot_by_type():
    res = ResMsg()
    types = ['阅读', '写作', '翻译', '完型填空']
    result = {}

    for t in types:
        # 查询条件: 确保按题型筛选数据
        items = db.session.query(TbItem.title, TbItem.pdf_url).filter(TbItem.type.like(f"%{t}%")).order_by(TbItem.source_year.desc()).limit(4).all()

        # 打印查询结果以调试
        print(f"查询结果 (题型: {t}):", items)

        result[t] = [{'title': item.title, 'pdf_url': item.pdf_url} for item in items]

    res.update(code=ResponseCode.SUCCESS, data=result)

    # 打印返回的结果
    print("最终返回的数据:", result)
    return res.data

# 按题型分类获取用户推荐（UserCF）
@jobBp.route('/grnn_recommend', methods=['GET'])
def grnn_recommend():
    user_id = request.args.get('userId')
    question_type = request.args.get('type', None)  # 获取传入的题型

    try:
        # 初始化推荐器并传递 user_id
        recommender = GRNN_DE_Recommender(user_id=int(user_id))

        # 训练推荐模型
        recommender.train(db.session)

        # 获取推荐结果
        recs = recommender.recommend(int(user_id), top_k=100)  # 推荐前 10 个试题

        # 获取试题详情
        items = []
        for iid, score in recs:
            item = db.session.query(TbItem).filter(TbItem.id == iid).first()
            if item:
                # 如果 question_type 存在，过滤掉不匹配的试题
                if question_type and item.type != question_type:
                    continue  # 如果试题的类型不匹配，跳过该试题
                items.append({
                    'id': item.id,
                    'title': item.title,
                    'type': item.type,
                    'content': item.content[:100] + '...',  # 摘要
                    'difficulty': item.difficulty,
                    'score_avg': item.score_avg,
                    'pdf_url': item.pdf_url,
                    'knowledge_points': item.knowledge_points,
                    'recommend_score': float(score)
                })

        # 按题型分类
        typed_data = {'阅读理解': [], '翻译': [], '写作': [], '完型填空': []}
        for item in items:
            if item['type'] in typed_data:
                typed_data[item['type']].append(item)

        # 每种题型最多4个
        for key in typed_data:
            typed_data[key] = sorted(typed_data[key], key=lambda x: x['recommend_score'], reverse=True)[:4]

        # 返回推荐试题数据
        return jsonify({
            'code': 200,
            'data': typed_data
        })

    except Exception as e:
        return jsonify({
            'code': 500,
            'msg': f'推荐失败: {str(e)}'
        })


# 词云使用--分词接口
@jobBp.route('/getWordCut', methods=["GET"])
def getWordCut():
    res = ResMsg()
    result = getWords()
    res.update(code=ResponseCode.SUCCESS, data=result)
    return res.data


# 词云使用hdfs
@jobBp.route('/ReadCloudHdfs', methods=['GET'])
def ReadCloudHdfs():
    # HDFS中文件的路径，比如 /user/root/wordcloud.json
    hdfs_file_path = '/AfterCleanData/word_frequency_result.json'

    file_content = read_hdfs_file(hdfs_file_path)
    if file_content.startswith("读取失败"):
        return jsonify({'code': 500, 'msg': file_content})

    try:
        # 解析读取到的JSON内容
        wordcloud_data = json.loads(file_content)
        return jsonify({'code': 200, 'msg': '读取成功', 'data': wordcloud_data})
    except Exception as e:
        return jsonify({'code': 500, 'msg': f'解析JSON失败: {e}'})


@jobBp.route('/ReadByLevel', methods=['GET'])
def ReadByLevel():
    level = request.args.get('level')
    file_mapping = {
        "beginner": "/AfterCleanData/beginner.json",
        "elementary": "/AfterCleanData/elementary.json",
        "intermediate": "/AfterCleanData/intermediate.json",
        "upper_intermediate": "/AfterCleanData/upper_intermediate.json",
        "advanced": "/AfterCleanData/advanced.json"
    }

    if level not in file_mapping:
        return jsonify({'code': 400, 'msg': '参数错误: 不支持的级别'})

    hdfs_file_path = file_mapping[level]
    file_content = read_hdfs_file(hdfs_file_path)
    if file_content.startswith("读取失败"):
        return jsonify({'code': 500, 'msg': file_content})

    try:
        # 解析读取到的JSON内容
        wordcloud_data = json.loads(file_content)
        return jsonify({'code': 200, 'msg': '读取成功', 'data': wordcloud_data})
    except Exception as e:
        return jsonify({'code': 500, 'msg': f'解析JSON失败: {e}'})




# 词频统计 - yearly_pos_frequency.json
@jobBp.route('/ReadYearlyPosFrequencyHdfs', methods=['GET'])
def ReadYearlyPosFrequencyHdfs():
    # HDFS 中文件的路径，比如 /user/root/yearly_pos_frequency.json
    hdfs_file_path = '/AfterCleanData/yearly_pos_frequency.json'

    file_content = read_hdfs_file(hdfs_file_path)
    if file_content.startswith("读取失败"):
        return jsonify({'code': 500, 'msg': file_content})

    try:
        # 解析读取到的JSON内容
        yearly_pos_frequency_data = json.loads(file_content)
        return jsonify({'code': 200, 'msg': '读取成功', 'data': yearly_pos_frequency_data})
    except Exception as e:
        return jsonify({'code': 500, 'msg': f'解析JSON失败: {e}'})


# 词频统计 - pie_chart_results.json
@jobBp.route('/ReadPieChartResultsHdfs', methods=['GET'])
def ReadPieChartResultsHdfs():
    # HDFS 中文件的路径，比如 /user/root/pie_chart_results.json
    hdfs_file_path = '/AfterCleanData/pie_chart_results.json'

    file_content = read_hdfs_file(hdfs_file_path)
    if file_content.startswith("读取失败"):
        return jsonify({'code': 500, 'msg': file_content})

    try:
        # 解析读取到的JSON内容
        pie_chart_results_data = json.loads(file_content)
        return jsonify({'code': 200, 'msg': '读取成功', 'data': pie_chart_results_data})
    except Exception as e:
        return jsonify({'code': 500, 'msg': f'解析JSON失败: {e}'})


# Library搜索
@jobBp.route('/get', methods=["GET"])
def get():
    res = ResMsg()
    keyword = request.args.get('keyword')
    # print(keyword)

    result = db.session.query(Job).filter(Job.position_name.like('%' + keyword + '%')).order_by(
        Job.publish_time.desc()).limit(8).all()
    data = job_schema.dump(result)
    res.update(code=ResponseCode.SUCCESS, data=data)
    return res.data

# 题库搜索
@jobBp.route('/paperGet', methods=["GET"])
def paper_get():
    res = ResMsg()
    try:
        keyword = request.args.get('keyword', '', type=str)

        # 构造查询
        query = db.session.query(TbExamPaper)
        if keyword:
            query = query.filter(TbExamPaper.title.like(f"%{keyword}%"))

        papers = query.order_by(TbExamPaper.year.desc()).limit(8).all()
        data = job_schema.dump(papers, many=True)

        res.update(code=ResponseCode.SUCCESS, data=data)
    except Exception as e:
        res.update(code=ResponseCode.FAIL, msg=f"查询出错: {str(e)}")

    return res.data




# 热门 / 最新
@jobBp.route('/getHot', methods=["GET"])
def getHot():
    res = ResMsg()
    result = db.session.query(Job).order_by(Job.publish_time.desc()).limit(4).all()
    data = job_schema.dump(result)
    res.update(code=ResponseCode.SUCCESS, data=data)
    return res.data


@jobBp.route('/getChart2', methods=["GET"])
def getChart2():
    res = ResMsg()
    datas = []
    for i in range(2001, 2021):
        cnt = db.session.query(Job).filter(Job.myear == i).count()
        chart = dict(name=i, value=cnt)
        datas.append(chart)
    res.update(code=ResponseCode.SUCCESS, data=datas)
    return res.data


@jobBp.route('/getChart3', methods=["GET"])
def getChart3():
    res = ResMsg()
    result = db.session.query(Job.myear.label('name'), func.count('*').label('value')).group_by(Job.myear).order_by(
        Job.myear.asc()).all()
    datas = chart_data.dump(result)
    res.update(code=ResponseCode.SUCCESS, data=datas)
    return res.data


# @JobBp.before_request
# def init_session():
#     db.session = db.session.session_factory()

# 不同城市，不同学历的收入情况
# @jobBp.route('/getTypeRate', methods=["GET"])
# def getTypeRate():
#     res = ResMsg()
#     types = ['上海', '北京', '深圳', '广州', '苏州']
#
#     datas = []
#     for t in types:
#         data = []
#         jobs = db.session.query(Job).filter(Job.city.like('%' + t + '%'), Job.salary1 != 0).all()
#         for m in jobs:
#             rateData = []
#             rateData.append(formatDegree(m.degree))
#             rateData.append(m.salary1)
#             rateData.append(m.degree)
#             rateData.append(m.salary0)
#             rateData.append(m.position_name)
#             rateData.append(m.company_name)
#             data.append(rateData)
#         datas.append(data)
#     res.update(code=ResponseCode.SUCCESS, data=dict(datas=datas, labels=types))
#     return res.data


# @jobBp.route('/getTimeLine', methods=["GET"])
# def getTimeLine():
#     res = ResMsg()
#     types = ['美国', '英国', '日本', '中国香港', '中国大陆', '法国', '德国', '韩国', '意大利', '加拿大', '中国台湾',
#              '澳大利亚', '西班牙', '印度', '瑞士', '新西兰']
#     datas = []
#     for y in range(2000, 2021):
#         yearData = []
#         for t in types:
#             cnt = db.session.query(Job).filter(Job.myear == y, Job.nation.like('%' + t + '%')).count()
#             yearData.append(cnt)
#         datas.append(yearData)
#
#     res.update(code=ResponseCode.SUCCESS, data=dict(datas=datas))
#     return res.data



# 获取几个统计数字
@jobBp.route('/getPanel', methods=["GET"])
def getPanel():
    res = ResMsg()
    cnt1 = db.session.query(Job).count()
    cnt2 = db.session.query(func.count(distinct(Job.city))).scalar()
    cnt3 = db.session.query(func.count(distinct(Job.company_name))).scalar()
    cnt4 = db.session.query(func.count(distinct(Job.coattr))).scalar()

    res.update(code=ResponseCode.SUCCESS, data=dict(data1=cnt1, data2=cnt2, data3=cnt3, data4=cnt4))
    return res.data


from models import job


# 职位按照省份来分组统计（地图）
# @jobBp.route('/getCityJob', methods=["GET"])
# def getCityJob():
#     res = ResMsg()
#     cityList = job.cityList  # 从 job.cityList 获取省市数据
#
#     # 执行查询，统计每个城市的职位数量
#     result = db.session.query(
#         Job.city.label('name'),  # 城市名称
#         func.count('*').label('value')  # 职位数量
#     ).group_by(Job.city).order_by(
#         func.count('*').desc()  # 按职位数量降序排序
#     ).all()
#
#     # 打印查询结果，检查是否返回数据
#     # print("查询结果:", result)
#
#     province_counts = {}  # 用于存储每个省份的职位数量
#
#     for city, count in result:
#         # 遍历所有省份，检查该城市是否属于某个省份
#         province = None  # 用于保存匹配到的省份
#         for item in cityList:
#             province_name = item['province']  # 省份名称
#             for city_prefix in item['city']:  # 遍历该省份下的城市
#                 if city in city_prefix:  # 如果城市名包含在当前的 `city_prefix` 中
#                     province = province_name
#                     break  # 找到省份后跳出当前城市循环
#             if province:  # 如果已经匹配到省份，跳出外层循环
#                 break
#
#         # 如果找到对应的省份，累加该省份的职位数量
#         if province:
#             province_counts[province] = province_counts.get(province, 0) + count
#         else:
#             # 如果未找到省份，归类为 '未知'
#             province_counts['未知'] = province_counts.get('未知', 0) + count
#
#     # 打印所有的省份和职位数量
#     # print("省份职位统计:", province_counts)
#
#     # 将结果转换为适合前端显示的格式
#     datas = [{"name": province, "value": count} for province, count in province_counts.items()]
#
#     # 返回响应
#     res.update(code=ResponseCode.SUCCESS, data=datas)
#
#     return res.data

#
# # 职位按照城市来分组统计
# @jobBp.route('/getCityJob2', methods=["GET"])
# def getCityJob2():
#     res = ResMsg()
#     result = db.session.query(Job.city.label('name'), func.count('*').label('value')).group_by(Job.city).order_by(
#         Job.city.asc()).all()
#     datas = chart_data.dump(result)
#     res.update(code=ResponseCode.SUCCESS, data=datas)
#     return res.data
#
#
# # 按照公司类型分组统计
# @jobBp.route('/getTypeRank', methods=["GET"])
# def getTypeRank():
#     res = ResMsg()
#     result = db.session.query(Job.coattr.label('name'), func.count('*').label('value')).group_by(Job.coattr).order_by(
#         func.count('*').desc()).all()
#     datas = chart_data.dump(result)
#     res.update(code=ResponseCode.SUCCESS, data=datas)
#     return res.data


#neo4j“词汇-话题”知识图谱
@jobBp.route('/getGraphData', methods=['GET'])
def getGraphData():
    graph = Graph("bolt://master:7687", auth=("neo4j", "Sjy123456"))
    # 获取所有节点和关系
    nodes = graph.run("MATCH (n) RETURN n").data()
    # relationships = graph.run("MATCH (a)-[r:SAME_THEME]->(b) RETURN a, r, b").data()
    relationships = graph.run("""
            MATCH (a)-[r:SAME_THEME]->(b) 
            RETURN a.name as source, b.name as target, r.theme as theme
        """).data()

    nodes_data = []
    for node in nodes:
        nodes_data.append({
            'id': node['n']['name'],
            'label': node['n']['name'],
            'scores': node['n']['相关性'],
            'category': node['n'].get('所属阅读话题', '未分类'),
            'explanation': node['n'].get('释义', '暂无说明'),
        })

    edges_data = []
    for rel in relationships:
        edges_data.append({
            'source': str(rel['source']),  # 确保为字符串
            'target': str(rel['target']),
            'label': rel.get('theme', 'SAME_THEME')
        })

    return jsonify({'nodes': nodes_data, 'edges': edges_data})


# # 按照需求的学历分组统计
# @jobBp.route('/getDegreeRank', methods=["GET"])
# def getDegreeRank():
#     res = ResMsg()
#     result = db.session.query(Job.degree.label('name'), func.count('*').label('value')).group_by(Job.degree).order_by(
#         func.count('*').desc()).all()
#     datas = chart_data.dump(result)
#     res.update(code=ResponseCode.SUCCESS, data=datas)
#     return res.data


@jobBp.after_request
def close_session(response):
    db.session.close()
    return response




@jobBp.route('/chat', methods=['POST'])
def chat():
# 初始化 OpenAI 客户端
    client = OpenAI(
        api_key="514c84d600d7448bb9c81cbba77ae28c.E5aMEcijkvLR2Ux1",
        base_url="https://open.bigmodel.cn/api/paas/v4/"
    )
    if not request.is_json:
        return jsonify({"error": "请求体不是 JSON 格式"}), 400

    data = request.get_json()
    if not data or 'prompt' not in data:
        return jsonify({"error": "缺少 'prompt' 参数"}), 400

    prompt = data['prompt']

    try:
        completion = client.chat.completions.create(
            model="glm-4",
            messages=[
                {"role": "user", "content": prompt},
            ],
            top_p=0.7,
            temperature=0.9
        )
        response = completion.choices[0].message.content
        return jsonify({"response": response}), 200
    except Exception as e:
        import traceback
        traceback.print_exc()
        return jsonify({"error": str(e)}), 500

